﻿#include<stdio.h>
#include<windows.h>

//归并排序，递归实现
void _MergeSort(int* a, int left, int right, int* temp)
{
	//分解
	if (left >= right)
		return;
	int mid = (left + right) >> 1;
	_MergeSort(a, left, mid, temp);
	_MergeSort(a, mid + 1, right, temp);

	//合并
	int start1 = left;
	int start2 = mid + 1;
	int i = left;
	while (start1 <= mid && start2 <= right)
	{
		if (a[start1] > a[start2])
		{
			temp[i++] = a[start2++];
		}
		else
		{
			temp[i++] = a[start1++];
		}
	}
	while (start1 <= mid)
	{
		temp[i++] = a[start1++];
	}
	while (start2 <= right)
	{
		temp[i++] = a[start2++];
	}
	for (i = left;i <= right;i++)
	{
		a[i] = temp[i];
	}
}

// 归并排序非递归实现
void MergeSortNonR(int* a, int n)
{
	int* temp = (int*)malloc(sizeof(int) * n);
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0;i < n;i += 2 * gap)
		{
			int start1 = i, end1 = i + gap - 1;
			int start2 = i + gap, end2 = i + 2 * gap - 1;
			int cur = i;
			// 归并过程中右半区间可能就不存在,就跳过循环，留给下一次排序
			if (start2 >= n)
			{
				break;
			}
			// 归并过程中右半区间算多了, 修正一下
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			while (start1 <= end1 && start2 <= end2)
			{
				if (a[start1] > a[start2])
				{
					temp[cur++] = a[start2++];
				}
				else
				{
					temp[cur++] = a[start1++];
				}
			}
			while (start1 <= end1)
			{
				temp[cur++] = a[start1++];
			}
			while (start2 <= end2)
			{
				temp[cur++] = a[start2++];
			}
			for (int j = i;j <= end2;j++)
			{
				a[j] = temp[j];
			}
		}
		gap *= 2;
	}
	free(temp);
}

// 计数排序
void CountSort(int* a, int n)
{
	int max = a[0], min = a[0];
	for (int i = 0;i < n;i++)
	{
		if (max < a[i])
		{
			max = a[i];
		}
		if (min > a[i])
		{
			min = a[i];
		}
	}
	int range = max - min + 1;
	int* temp = (int*)malloc(sizeof(int) * range);
	memset(temp, 0, sizeof(int) * range);
	for (int i = 0;i < n;i++)
	{
		temp[a[i] - min]++;
	}
	int j = 0;
	for (int i = 0;i < range;i++)
	{
		while (temp[i]--)
		{
			a[j++] = i + min;
		}
	}

	free(temp);
}

void PrintArr(int* a, int n)
{
	for (int i = 0;i < n;i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

void MergeSort(int* a, int n)
{
	int* temp = (int*)malloc(sizeof(int) * n);
	_MergeSort(a, 0, n - 1, temp);
	free(temp);
}

void TestMergeSort()
{
	int a[] = { 10,6,7,1,3,9,4,2,8 };
	int n = sizeof(a) / sizeof(a[0]);
	MergeSortNonR(a, n);
	PrintArr(a, n);
}

void TestCountSort()
{
	int a[] = { 49,38,65,97,76,13,27,49 };
	int n = sizeof(a) / sizeof(a[0]);
	CountSort(a, n);
	PrintArr(a, n);
}

int main(void)
{
	//TestMergeSort();
	TestCountSort();

	system("pause");
	return 0;
}